/*
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function custom_ctor(a, b) {
    this.a = a;
    this.b = b;
}

function custom_ctor_returning_val() {
    this.a = 42
    return 123
}

class BaseClass {
    constructor() {
        this.prop = 42
    }
}

class SubclassWithoutCtor extends BaseClass {
}

class SubclassWithCtor extends BaseClass {
    constructor() {
        super()
        this.subprop = 0
    }
}

function f1() {
    this.constructor.prototype.arguments = "123"
    return arguments
}

class InvalidSubclass extends BaseClass {
    constructor() {
        super()
        return Number()
    }
}

function alloc_1() {
    var obj = new custom_ctor(1, 2)
    if (obj.a != 1 || obj.b != 2) {
        throw "invalid object"
    }
}

function alloc_2() {
    var obj = new custom_ctor_returning_val()
    if (obj == 123) {
        throw "not an object"
    }
    if (obj.a != 42) {
        throw "invalid object"
    }
}

function alloc_3() {
    var obj = new Number(42)
    if (obj != 42) {
        throw "invalid value: " + obj
    }
}

function alloc_4() {
    var obj = new BaseClass()
    if (obj.prop != 42) {
        throw "invalid object"
    }
}

function alloc_5() {
    var obj = new SubclassWithCtor()
    if (obj.prop != 42 || obj.subprop != 0) {
        throw "invalid object"
    }
}

function alloc_6() {
    var obj = new SubclassWithoutCtor()
    if (obj.prop != 42) {
        throw "invalid object"
    }
}

function alloc_7() {
    var obj = new f1(1, 2, 3, 4, 5)
    if (obj[2] != 3) {
        throw "invalid object"
    }
}

function alloc_8() {
    var obj = null
    try {
        obj = new InvalidSubclass()
    } catch (e) {
        if (e instanceof TypeError) {
            return
        }
        throw e
    }
    throw new "invalid object"
}

//! CHECKER      Expand new object dyn range
//! RUN          options: "--compiler-hotness-threshold=0 --compiler-ecma-newobj-profiling=false --compiler-regex _GLOBAL::alloc_.*", entry: "_GLOBAL::func_main_0"
//! METHOD       "alloc_1"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_2"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_3"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_4"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_5"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_6"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_7"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_8"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/

//! CHECKER      Expand new object dyn range in AOT mode
//! RUN_PAOC     options: " --compiler-ecma-newobj-profiling=false --compiler-regex '_GLOBAL::alloc_.*'"
//! METHOD       "alloc_1"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_2"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_3"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_4"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_5"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_6"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_7"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! METHOD       "alloc_8"
//! PASS_AFTER   "IrBuilder"
//! INST_NOT     /Intrinsic.AllocDynObject.*/
//! PASS_AFTER   "Codegen"
//! INST         /Intrinsic.AllocDynObject.*/
//! RUN options: "--compiler-enable-jit=false", entry: "_GLOBAL::func_main_0", force_jit: false
RuntimeTesting.PrepareFunctionForOptimization(alloc_1);
alloc_1()
RuntimeTesting.OptimizeFunctionOnNextCall(alloc_1);

RuntimeTesting.PrepareFunctionForOptimization(alloc_2);
alloc_2()
RuntimeTesting.OptimizeFunctionOnNextCall(alloc_2);

RuntimeTesting.PrepareFunctionForOptimization(alloc_3);
alloc_3()
RuntimeTesting.OptimizeFunctionOnNextCall(alloc_3);

RuntimeTesting.PrepareFunctionForOptimization(alloc_4);
alloc_4()
RuntimeTesting.OptimizeFunctionOnNextCall(alloc_4);

RuntimeTesting.PrepareFunctionForOptimization(alloc_5);
alloc_5()
RuntimeTesting.OptimizeFunctionOnNextCall(alloc_5);

RuntimeTesting.PrepareFunctionForOptimization(alloc_6);
alloc_6()
RuntimeTesting.OptimizeFunctionOnNextCall(alloc_6);

RuntimeTesting.PrepareFunctionForOptimization(alloc_7);
alloc_7()
RuntimeTesting.OptimizeFunctionOnNextCall(alloc_7);

RuntimeTesting.PrepareFunctionForOptimization(alloc_8);
alloc_8()
RuntimeTesting.OptimizeFunctionOnNextCall(alloc_8);

for (var i = 0; i < 5; ++i) {
    alloc_1()
    alloc_2()
    alloc_3()
    alloc_4()
    alloc_5()
    alloc_6()
    alloc_7()
    alloc_8()
}